package com.cwz.quartz.config;

import org.quartz.Scheduler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;

import javax.sql.DataSource;
import java.util.Properties;

/**
 * @program: w-demo
 * @description: 定时任务配置（单机部署建议删除此类和 qrtz 数据库表，默认走内存会最高效）
 * 对于调度器 Schedule 来说，一个调度器可以调度多个 job 和 trigger，就不用创建多个调度器，单例就可以
 * @author: Wen
 **/
@Configuration
public class ScheduleConfig {
	@Bean
	public Scheduler scheduler(DataSource dataSource) {
		return schedulerFactoryBean(dataSource).getScheduler();
	}

	@Bean
	public SchedulerFactoryBean schedulerFactoryBean(DataSource dataSource) {
		SchedulerFactoryBean factory = new SchedulerFactoryBean();
		// 调度器名称
		factory.setSchedulerName("wdemoScheduler");
		// 数据源
		factory.setDataSource(dataSource);
		// 延时启动
		factory.setStartupDelay(1);
		// 当前调度器在整个 ioc 容器中的 key（可设置可不设置）
		factory.setApplicationContextSchedulerContextKey("applicationContextKey");
		// 可选，QuartzScheduler
		// 启动时更新己存在的 Job，这样就不用每次修改 targetObject 后删除 qrtz_job_details 表对应记录了
		factory.setOverwriteExistingJobs(true);
		// 设置自动启动，默认为 true
		factory.setAutoStartup(true);

		// quartz 参数
		Properties prop = new Properties();
		// 调度标识名 集群中每一个实例都必须使用相同的名
		prop.put("org.quartz.scheduler.instanceName", "wdemoScheduler");
		// ID设置为自动获取 每一个必须不同
		prop.put("org.quartz.scheduler.instanceId", "AUTO");
		// 线程池配置
		// 线程池的实现类
		prop.put("org.quartz.threadPool.class", "org.quartz.simpl.SimpleThreadPool");
		// 指定线程数
		prop.put("org.quartz.threadPool.threadCount", "20");
		// 设置线程优先级
		prop.put("org.quartz.threadPool.threadPriority", "5");
		// JobStore 配置
		// 数据保存方式为数据库持久化 springboot > 2.5.6后使用 LocalDataSourceJobStore
		prop.put("org.quartz.jobStore.class", "org.springframework.scheduling.quartz.LocalDataSourceJobStore");
		// 集群配置
		// 是否加入集群
		prop.put("org.quartz.jobStore.isClustered", "true");
		// 调度实例失效的检查时间间隔 ms
		prop.put("org.quartz.jobStore.clusterCheckinInterval", "15000");
		prop.put("org.quartz.jobStore.maxMisfiresToHandleAtATime", "1");
		prop.put("org.quartz.jobStore.txIsolationLevelSerializable", "true");
		// 当设置为 true 是，此属性告诉 quartz 在非托管 JDBC 连接上调用 setTransactionIsolation（其实就是事务托管）
		prop.put("org.quartz.jobStore.txIsolationLevelReadCommitted", "true");
		// quartz 错误触发阈值（就是在 12000s 内任务还会继续执行，超过 12000s 就执行错误触发策略）
		prop.put("org.quartz.jobStore.misfireThreshold", "12000");
		// quartz 表名前缀
		prop.put("org.quartz.jobStore.tablePrefix", "QRTZ_");
		factory.setQuartzProperties(prop);
		return factory;
	}
}
